import { Vector3 } from '@babylonjs/core/Maths/math';
import { HardLineGeometry, IHardLineGeometryOptions } from './hard-line-geometry';
import { Scene } from '@babylonjs/core/scene';
import { Mesh } from '@babylonjs/core/Meshes/mesh';
import { Buffer } from '@babylonjs/core/Buffers/buffer';

/**
 * 间隔线几何体参数对象
 * @param dashSize 虚线段长度
 * @param gapSize 虚线空白长度
 */
interface IStripsLineGeometryOptions {
    dashSize?: number,
    gapSize?: number
}


/**
 * 间隔线几何体（每两个顶点为一条线段，不支持箭头）
 * @param name 几何体id
 * @param vertices 顶点集
 * @param options 参数对象
 * @param scene 所在场景
 * @param mesh 应用到的网格
 */
class StripsLineGeometry extends HardLineGeometry {

    private _counts!: Float32Array;

    constructor(name: string, vertices: Vector3[], options?: Partial<IStripsLineGeometryOptions>, scene?: Scene, mesh?: Mesh) {
        super(name, vertices, options, scene, mesh);
    }

    public update(): void {
        super.update();
        this.getVertexBuffer('count')?.update(this._counts);
    }
    protected initializeVariable(vertices: Vector3[], options?: IHardLineGeometryOptions | undefined): void {
        super.initializeVariable(vertices, options);
        const s1 = (this._maxSegments * 2 - 3) * 6;
        this._counts = new Float32Array(s1);
    }
    protected setAttribute(): void {
        super.setAttribute();
        const engine = this.getEngine();

        const bfr = this.getVertexBuffer('count');
        if (bfr) bfr.dispose();
        const countRefBuffer = new Buffer(engine, this._counts, true, 1);
        this.setVerticesBuffer(countRefBuffer.createVertexBuffer('count', 0, 1));
    }
    protected rectifyPoints(ps: Vector3[]): Vector3[] {
        return ps;
    }
    protected resizeDataArray(length1: number, length3: number): void {
        super.resizeDataArray(length1, length3);
        this._counts = new Float32Array(length1);
    }
    protected pushData(...datas: Array<number | Vector3>): void {
        const i3 = datas[0] as number;
        const i1 = datas[1] as number;
        const c = datas[2] as Vector3;
        const n = datas[3] as Vector3;
        const o = datas[4] as number;
        const ct = datas[5] as number;

        this._offsets[i1] = o;
        this._counts[i1] = ct;
        this._vertices[i3] = c.x;
        this._vertices[i3 + 1] = c.y;
        this._vertices[i3 + 2] = c.z;
        this._nextVertices[i3] = n.x;
        this._nextVertices[i3 + 1] = n.y;
        this._nextVertices[i3 + 2] = n.z;
    }
    protected pushSolidData(vs: Vector3[]): void {
        const n0 = this._tV0;
        const n1 = this._tV1;
        for (let i = 0; i < vs.length - 1; i++) {
            const cp = vs[i];
            const np = vs[i + 1];
            const c0 = i;
            const c1 = i + 1;
            if (i === 0) {
                n0.copyFrom(np);
                n1.copyFrom(np).subtractInPlace(cp).normalize().addInPlace(np);
                this.pushData(0, 0, cp, n0, 1, c0);
                this.pushData(3, 1, cp, n0, -1, c0);
                this.pushData(6, 2, np, n1, 1, c1);
                this.pushData(9, 3, cp, n0, -1, c0);
                this.pushData(12, 4, np, n1, -1, c1);
                this.pushData(15, 5, np, n1, 1, c1);
            } else {
                const i3 = 18 + (i - 1) * 36;
                const i1 = 6 + (i - 1) * 12;
                n0.copyFrom(np);
                n1.copyFrom(np).subtractInPlace(cp).normalize().addInPlace(np);
                this.pushData(i3 + 18, i1 + 6, cp, n0, 1, c0);
                this.pushData(i3 + 21, i1 + 7, cp, n0, -1, c0);
                this.pushData(i3 + 24, i1 + 8, np, n1, 1, c1);
                this.pushData(i3 + 27, i1 + 9, cp, n0, -1, c0);
                this.pushData(i3 + 30, i1 + 10, np, n1, -1, c1);
                this.pushData(i3 + 33, i1 + 11, np, n1, 1, c1);
            }
        }
    }
}


export { StripsLineGeometry };
export type { IStripsLineGeometryOptions };